﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace 综合同步
{
    public class ProtocolData
    {
        static ulong m_packageNo;
        static object m_mutex = new object();
        static ulong PackNo { get { lock (m_mutex) return ++m_packageNo; } }

        TcpClient m_client;
        Action<TcpClient,PACKAGE_INFO> m_RecvAction;

        #region 属性
        byte[] m_bufRecv = new byte[1024];
        public byte[] RecvBuf
        {
            get { return m_bufRecv; }
        }
        int m_leftByte = 0;
        public int LeftByte
        {
            get { return m_leftByte; }
            set { m_leftByte = value; }
        }
        int m_processIndex = 0;
        public int ProcessIndex
        {
            get { return m_processIndex; }
            set { m_processIndex = value; }
        }
        #endregion
        public ProtocolData(TcpClient client, Action<TcpClient,PACKAGE_INFO> recv)
        {
            m_client = client;
            m_RecvAction = recv;
        }
        public void RecvPackageData()
        {
            try
            {
                while (LeftByte > 12)
                {
                    if (RecvBuf[(ProcessIndex)% RecvBuf.Length] == 'd' && RecvBuf[(ProcessIndex + 1)% RecvBuf.Length] == 'i' &&
                        RecvBuf[(ProcessIndex + 2)% RecvBuf.Length] == 'n' && RecvBuf[(ProcessIndex + 3)% RecvBuf.Length] == 'g' &&
                        RecvBuf[(ProcessIndex + 4)% RecvBuf.Length] == 'h' && RecvBuf[(ProcessIndex + 5)% RecvBuf.Length] == 'a' &&
                        RecvBuf[(ProcessIndex + 6)% RecvBuf.Length] == 'n' && RecvBuf[(ProcessIndex + 7)% RecvBuf.Length] == 't' &&
                        RecvBuf[(ProcessIndex + 8)% RecvBuf.Length] == 'e' && RecvBuf[(ProcessIndex + 9)% RecvBuf.Length] == 'c' &&
                        RecvBuf[(ProcessIndex + 10)% RecvBuf.Length] == 'h' && RecvBuf[(ProcessIndex + 11)% RecvBuf.Length] == 0)
                    {
                        IEnumerable<byte> readData = RecvBuf.Skip(ProcessIndex);
                        int readDataLen = readData.Count();
                        if (readDataLen < LeftByte) readData = readData.Concat(RecvBuf.Take(LeftByte - readDataLen));
                        PACKAGE_INFO data = ClassByteConvert.CByte2Class<PACKAGE_INFO>(readData.ToArray());
                        if (data != null)
                        {
                            int packLen = Marshal.SizeOf(typeof(PACKAGE_INFO)) + (int)data.datalen - 1;
                            if (LeftByte < packLen) break;
                            LeftByte -= packLen;
                            ProcessIndex = (ProcessIndex + packLen) % RecvBuf.Length;
                            //检查校验和
                            if (data.checkcode == readData.Take(44).Sum(o => o))
                                m_RecvAction(m_client, data);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (LeftByte <= 0) break;
                        LeftByte--;
                        ProcessIndex = (ProcessIndex+1) % RecvBuf.Length;
                    }
                }
            }
            catch(Exception ex)
            {
                FileLogOperator.Error(ex.Message);
                FileLogOperator.Error(ex.StackTrace);
            }
        }
    }
}
